package it.polito.connectedcar.vehicle;

import it.polito.appeal.traci.connectedcar.sumo.SUMOVehicle;
import it.polito.appeal.traci.connectedcar.vehicle.VehicleDataListener;
import it.polito.connectedcar.tcc.zone.Token;

import java.awt.geom.Point2D;
import java.io.IOException;

/**
 * The adapter class is the bridge between a proxy ( known by high levels ) and
 * the source entity managing data The {@link SUMOVehicleAdapter} is attached to
 * the simulation provided Vehicle's representation. It implements the
 * {@link VehicleDataListener} interface in order to be informed when the SUMO
 * entity has fresh data ready to be published. The job of this class is to
 * receive updates from low levels and to forward them by using the
 * {@link VehicleUpdateDelegate} Delegate. By decoupling the interface
 * definitions of low level objects and high levels objects, it will be possible
 * to attach to different Source entities ( real or simulated) without changing
 * the business logic and behavior.
 * 
 * @author Nicola Aresta
 * 
 */
public class SUMOVehicleAdapter extends SourceVehicleProxy
		implements
			VehicleDataListener {

	private SUMOVehicle vehicle;
	private SUMOVehicleToken vehicleIdentificationToken;

	public SUMOVehicleAdapter(SUMOVehicle vehicle) {
		this.vehicle = vehicle;
		this.vehicleIdentificationToken = new SUMOVehicleToken(vehicle.getID());
		this.vehicle.setDataListener(this);
	}

	@Override
	public void setSpeed(double speed) {
		try {
			vehicle.setSpeed(speed);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@Override
	public void slowDown(float speed, int duration) {
		try {
			// vehicle.changeSpeedMode(false, false, false);
			vehicle.slowDown(speed, duration);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	@Override
	public double getSpeed() {
		return vehicle.getSpeed();
	}

	@Override
	public double getDirection() {
		// since in SUMO all the degrees are positive , we have to trigonometric
		// converts them to be used for real direcion estimation
		Double direction = vehicle.getDirection();
		return direction > 0 ? direction - 90 : Math.abs(direction) + 90;
	}

	@Override
	public Point2D getPosition() {
		return vehicle.getPosition();
	}

	@Override
	public void onLocationChange(Point2D utmPosition) {
		getVehicleUpdateDelegate().onLocationChange(utmPosition);
	}

	@Override
	public void onDirectionChange(double angle) {
		getVehicleUpdateDelegate().onDirectionChange(angle);
	}

	@Override
	public void onSpeedChange(double speed) {
		getVehicleUpdateDelegate().onSpeedChange(speed);
	}

	@Override
	public Token getVehicleIdentificationNumber() {
		return vehicleIdentificationToken;
	}

	@Override
	public String getCurrentLaneId() {
		return vehicle.getLaneId();
	}

	@Override
	public long getCurrentTime() {
		return vehicle.getSimTime();
	}

	@Override
	public void onLaneChange(String laneId) {
		getVehicleUpdateDelegate().onLaneChange(laneId);

	}
}
